/**
 * carousel - jQuery plugin to navigate images/any content in a carousel style widget.
 * @requires jQuery v1.2 or above
 *
 * Copyright (c) 2009 Dennis Hall <http://www.google.com/profiles/103490491683374491591>
 * - heavily modified from the 2007 original version
 * Copyright (c) 2007 Ganeshji Marwaha (gmarwaha.com)
 * http://gmarwaha.com/jquery/jcarousellite/
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 1.0.1a
 */


(function($) {                                                  // Compliant with jQuery.noConflict()
    
    $.fn.carousel = function(o) {
        o = $.extend({
            btnPrev: null,
            btnNext: null,
            btnGo: null,
            mouseWheel: false,
            auto: null,
            speed: 500,
            easing: null,
            vertical: false,
            circular: false,
            visible: 5,
            autoSize: false,
            start: 0,
            scroll: 5,
            beforeStart: null,
            afterEnd: null
        }, o || {});
        
        return this.each(function() {                           // Returns the element collection. Chainable.

            var running = false,
                animCss = o.vertical ? "top" : "left",
                sizeCss = o.vertical ? "height" : "width",
                div = $(this),
                ul = $("ul", div),
                tLi = $("li", ul),
                tl = tLi.size(),
                v = o.visible,
                disabledClass = 'disabled';
            ///

            if(o.circular) {
                ul.prepend(tLi.slice(tl-v-1+1).clone()).append(tLi.slice(0,v).clone());
                o.start += v;
            }
            
            var li = $("li", ul),
                numItems = li.size(),
                curr = o.start;
            ///
            
            // if we are trying to start with an item that is too close to the end of the list,
            // we don't want it to be the first item.
            if(curr > numItems - v){
                curr = numItems - v;
            }

            li.css({overflow: "hidden", 'float': (o.vertical ? "none" : "left")});
            ul.css({margin: "0", padding: "0", position: "relative", "list-style-type": "none", "z-index": "1"});
            div.css({overflow: "hidden", position: "relative", "z-index": "2", left: "0px"});

            var liSize = o.vertical ? height(li) : width(li),   // Full li size(incl margin)-Used for animation
                ulSize = liSize * numItems,                     // size of full ul(total length, not just for the visible items)
                divSize = liSize * v;                           // size of entire div(total length for just the visible items)
            ///
            
            //li.css({width: li.width(), height: li.height()});
            li.css({sizeCss:liSize});
            ul.css(sizeCss, ulSize+"px").css(animCss, -(curr*liSize));

            o.autoSize && div.css(sizeCss, divSize+"px");       // Width of the DIV. length of visible images
            
            function prev(){
                return go(curr - o.scroll);
            }
            
            function next(){
                return go(curr + o.scroll);
            }
            
            // make scrolling prev/next publicly accessible, for example:
            //   <code>$('.my-particular-carousel').trigger('scroll_prev');</code>
            div.bind('scroll_prev', prev);
            div.bind('scroll_next', next);
            div.bind('scroll_update', function(){
                tLi = $('li',ul);
                numItems = tLi.size();
                // if the number of items remaining is equal to the number of items to display at a time,
                // then make sure to scroll to the first item
                // else if we removed an item that is in the last 'page' of items,
                // then make sure to scroll back one so we don't leave a blank space at the end.
                return go(numItems == v ? 0 : tLi.index(arguments[1]) == numItems ? numItems : curr);
            });
            
            if(o.btnPrev){
                o.btnPrev = $(o.btnPrev, div.parent()).klik(prev).css('display','block');
            }
            
            if(o.btnNext){
                o.btnNext = $(o.btnNext, div.parent()).klik(next).css('display','block');
            }

            if(!o.circular && o.start == 0 && o.btnPrev){
                o.btnPrev.addClass(disabledClass);
            }

            if(o.btnGo)
                $.each(o.btnGo, function(i, val) {
                    $(val).click(function() {
                        return go(o.circular ? o.visible+i : i);
                    });
                });

            if(o.mouseWheel && div.mousewheel)
                div.mousewheel(function(e, d) {
                    return d>0 ? go(curr-o.scroll) : go(curr+o.scroll);
                });

            if(o.auto)
                setInterval(function() {
                    go(curr+o.scroll);
                }, o.auto+o.speed);

            function vis() {
                return li.slice(curr).slice(0,v);
            };

            function go(to) {
                if(!running) { //<strike>if to==curr, then we have nowhere to go, let's not waste time animating to where we already are.</strike>
					
					(o.beforeStart && o.beforeStart.call(this, vis()));
                    
                    //added because PGE requires dynamic items - you can click "no thanks" and the item will remove itself
                    //numItems = ul.find('li').size();

                    if(o.circular) {                    // If circular we are in first or last, then goto the other end
                        if(to<=o.start-v-1) {           // If first, then goto last
                            ul.css(animCss, -((numItems-(v*2))*liSize)+"px");
                            // If "scroll" > 1, then the "to" might not be equal to the condition; it can be lesser depending on the number of elements.
                            curr = to==o.start-v-1 ? numItems-(v*2)-1 : numItems-(v*2)-o.scroll;
                        } else if(to>=numItems-v+1) { // If last, then goto first
                            ul.css(animCss, -( (v) * liSize ) + "px" );
                            // If "scroll" > 1, then the "to" might not be equal to the condition; it can be greater depending on the number of elements.
                            curr = to==numItems-v+1 ? v+1 : v+o.scroll;
                        } else curr = to;
                    } else {                            // If non-circular and to points to first or last, we just return.
                        /** NEXT LINE CHANGED **/
                        curr = to < 0 ? 0 : to > numItems-v ? numItems-v : to;
                    }                                   // If neither overrides it, the curr will still be "to" and we can proceed.
                    
                    
                    running = true;
                    
                    ul.animate(
                        animCss == "left" ? { left: -(curr*liSize) } : { top: -(curr*liSize) } , o.speed, o.easing,
                        function() {
                            if(o.afterEnd){
                                o.afterEnd.call(this, vis());
                            }
                            running = false;
                        }
                    );
                    
                    // Disable buttons when the carousel reaches the last/first, and enable when not
                    if(!o.circular) {
                        // remove disabledClass
                        var both = o.btnPrev.add(o.btnNext).removeClass(disabledClass);
                        // add disabledClass if appropriate
                        var disableMe = (curr==0 && o.btnPrev) || (curr+o.scroll>=numItems && o.btnNext);
                        (disableMe && disableMe.addClass(disabledClass));
                        // if we have removed enough elements so that there is no need to scroll,
                        // then hide the scroll buttons
                        if(numItems <= o.visible){
                            both.css('display','none');
                        } 
						if(numItems > o.visible) {
							both.css('display','block');
						}
                    }

                }
                return false;
            };
            
            
        });
    };

    function css(el, prop) {
        return parseInt($.css(el[0], prop)) || 0;
    };
    function width(el) {
        return  el[0].offsetWidth + css(el, 'marginLeft') + css(el, 'marginRight');
    };
    function height(el) {
        return el[0].offsetHeight + css(el, 'marginTop') + css(el, 'marginBottom') + css(el, 'paddingTop') + css(el, 'paddingBottom');
    };
    
})(jQuery);


/* END MIT AND GPL LICENSING */

foo.mod.carousel = {
    init: function(){
        foo.log('foo.carousel.init');
        var $ = jQuery;
        $('.carousel').each(function(){
			var liWidth = $(this).find('ul:first').children(':first').outerWidth(true),
				cWidth = $(this).width() - 40, // the prev/next links are 40px total
				n = Math.ceil(cWidth/liWidth);
            var div = $(this).carousel({
                btnNext: ".next span",
                btnPrev: ".prev span",
                visible: n,
                scroll: n
            });
        });
    }
};
